package chances.declare.repo;

import static org.springframework.data.jpa.repository.query.QueryUtils.toOrders;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;

import chances.declare.entity.CPContent;
import chances.declare.entity.CPContentAndOplog;
import chances.declare.util.DateUtil;
import chances.declare.web.CPcontentQueryModel;
import chances.system.operator.entity.EnumData;
import chances.system.service.EnumService;

/**
* @Author WangCC
* @Date 2017年7月28日 下午2:13:53
* chances.declare.repo
* @Version 1.0
*/
public class CPContentRepositoryImpl {

    @PersistenceUnit
    private EntityManagerFactory emf;
    @Autowired
    EnumService enumService;

    private static final Logger logger = LoggerFactory.getLogger(CPContentRepositoryImpl.class);

    public Page<CPContent> findCPContentByOrgId(CPcontentQueryModel queryModel, Pageable pageable)
            throws ParseException {

        EntityManager em = emf.createEntityManager();
        CriteriaBuilder cb = em.getCriteriaBuilder();// 返回一个标准的实例，用于创建标准查询对象。
        CriteriaQuery<CPContent> cq = cb.createQuery(CPContent.class);
        Root<CPContent> root = cq.from(CPContent.class);

        Path<Long> sqlOrgId = root.get("orgId");// 组织id
        Path<Integer> sqlStatus = root.get("status");// 状态
        Path<String> sqlName = root.get("name");// 片名
        Path<String> sqlContentType = root.get("contentType");// 类型
        Path<Boolean> sqlIsAdopted = root.get("isAdopted");// 是否被采纳
        Path<Boolean> sqlExclusive = root.get("exclusive");// 是否独家
        Path<Date> sqlCreateTime = root.get("createTime");// 录入时间
        Path<Date> sqlDeclareTime = root.get("declareTime");// 申报时间
        Path<Date> sqlOnlineTime = root.get("onlineTime");// 上线时间

        List<Predicate> predicates = new ArrayList<Predicate>();

        predicates.add(cb.equal(sqlOrgId, queryModel.getOrgId()));// 根据orgId查询
        predicates.add(cb.notEqual(sqlStatus, CPContent.STATUS_DELETE));// 查询状态为非-1

        // 根据片名模糊查询
        if (StringUtils.isNotBlank(queryModel.getName())) {
            predicates.add(cb.like(sqlName, "%" + queryModel.getName() + "%"));
        }
        // 根据类型查询
        if (StringUtils.isNotBlank(queryModel.getContentType())) {
            predicates.add(cb.equal(sqlContentType, queryModel.getContentType()));
        }
        // 根据状态查询
        if (StringUtils.isNotBlank(queryModel.getStatus())) {
            predicates.add(cb.equal(sqlStatus, queryModel.getStatus()));
        }
        // 根据是否采纳查询
        if (StringUtils.isNotBlank(queryModel.getIsAdopted())) {
            predicates.add(cb.equal(sqlIsAdopted, queryModel.getIsAdopted()));
        }
        //判断是否为待处理工单
        if(queryModel.getAdoptSign().equals("order")){
            predicates.add(cb.notEqual(sqlIsAdopted, CPContent.ISADOPTED_AWAIT));
            predicates.add(cb.notEqual(sqlIsAdopted, CPContent.ISADOPTED_INIT));
        }
        // 根据是否独家查询
        if (StringUtils.isNotBlank(queryModel.getExclusive())) {
            if (queryModel.getExclusive().equals("true")) {
                predicates.add(cb.equal(sqlExclusive, CPContent.TRUE));
            } else if (queryModel.getExclusive().equals("false")) {
                predicates.add(cb.equal(sqlExclusive, CPContent.FALSE));
            }
        }
        // 所有大于录入开始时间的数据
        if (StringUtils.isNotBlank(queryModel.getCreateTimeBegin())) {
            Date createTimeBegin = DateUtil.StringTranslatedDate(queryModel.getCreateTimeBegin());
            predicates.add(cb.greaterThan(sqlCreateTime, createTimeBegin));
        }
        // 所有小于录入结束时间的数据
        if (StringUtils.isNotBlank(queryModel.getCreateTimeEnd())) {
            Date createTimeEnd = DateUtil.StringTranslatedDate(queryModel.getCreateTimeEnd());
            predicates.add(cb.lessThan(sqlCreateTime, createTimeEnd));
        }
        // 所有大于申报开始时间的数据
        if (StringUtils.isNotBlank(queryModel.getDeclareTimeBegin())) {
            Date declareTimeBegin = DateUtil.StringTranslatedDate(queryModel.getDeclareTimeBegin());
            predicates.add(cb.greaterThan(sqlDeclareTime, declareTimeBegin));
        }
        // 所有小于申报结束时间的数据
        if (StringUtils.isNotBlank(queryModel.getDeclareTimeEnd())) {
            Date declareTimeEnd = DateUtil.StringTranslatedDate(queryModel.getDeclareTimeEnd());
            predicates.add(cb.lessThan(sqlDeclareTime, declareTimeEnd));
        }
        // 所有大于上线开始时间的数据
        if (StringUtils.isNotBlank(queryModel.getOnlineTimeBegin())) {
            Date onlineTimeBegin = DateUtil.StringTranslatedDate(queryModel.getOnlineTimeBegin());
            predicates.add(cb.greaterThan(sqlOnlineTime, onlineTimeBegin));
        }
        // 所有小于上线结束时间的数据
        if (StringUtils.isNotBlank(queryModel.getOnlineTimeEnd())) {
            Date onlineTimeEnd = DateUtil.StringTranslatedDate(queryModel.getOnlineTimeEnd());
            predicates.add(cb.lessThan(sqlOnlineTime, onlineTimeEnd));
        }
        if (predicates.size() > 0) {
            Predicate[] predicatesArr = predicates.toArray(new Predicate[predicates.size()]);
            cq = cq.where(cb.and(predicatesArr));
            cq = cq.orderBy(toOrders(pageable.getSort(), root, cb));
        }
        cq = cq.orderBy(toOrders(pageable.getSort(), root, cb));
        List<CPContent> sql_count = em.createQuery(cq).getResultList();

        List<CPContent> sql_list = em.createQuery(cq)
                .setFirstResult(pageable.getPageNumber() * pageable.getPageSize())
                .setMaxResults(pageable.getPageSize()).getResultList();
        em.close();

        Page<CPContent> pageImpl = new PageImpl<CPContent>(sql_list, pageable, sql_count.size());

        return pageImpl;
    }

    @SuppressWarnings("unchecked")
    public Page<CPContentAndOplog> search(@Param("id") Long id, @Param("name") String name,
            @Param("operateType") String operateType, @Param("orgName") String orgName,
            @Param("opName") String opName, @Param("beginTime") String beginTime,
            @Param("endTime") String endTime, Pageable pageable) {
        EntityManager em = emf.createEntityManager();
        StringBuffer hql = new StringBuffer();
        hql.append("select new chances.declare.entity.CPContentAndOplog(cpContent,oplog) ");
        hql.append("from CPContent cpContent,Oplog oplog ");
        hql.append("where cpContent.id=oplog.objId ");
        if (id != null) {
            hql.append("and cpContent.id=:id ");
        }
        if (StringUtils.isNotBlank(name)) {
            hql.append("and cpContent.name like :name ");
        }
        if (StringUtils.isNotBlank(operateType)) {
            hql.append("and oplog.operateType=:operateType ");
        }
        if (StringUtils.isNotBlank(orgName)) {
            hql.append("and cpContent.orgId=:orgName ");
        }
        if (StringUtils.isNotBlank(opName)) {
            hql.append("and oplog.opName=:opName ");
        }
        if (StringUtils.isNotBlank(beginTime)) {
            hql.append("and oplog.operateTime > :beginTime ");
        }
        if (StringUtils.isNotBlank(endTime)) {
            hql.append("and oplog.operateTime <= :endTime ");
        }
        hql.append("order by oplog.operateTime desc ");
        Query cq = em.createQuery(hql.toString());
        // 把opName转化为名字
        List<EnumData> result = enumService.getEnumList("operatorEnum");
        for (EnumData enumdata : result) {
            if (enumdata.getValue().equals(opName)) {
                opName = enumdata.getName();
            }
        }
        // 日期转换
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate = null;
        Date endDate = null;
        if (StringUtils.isNotBlank(beginTime)) {
            try {
                beginDate = sdf.parse(beginTime);
            } catch (ParseException e) {
                logger.error(e.toString(), e);
            }
        }
        if (StringUtils.isNotBlank(endTime)) {
            try {
                Calendar c = Calendar.getInstance();
                c.setTime(sdf.parse(endTime));
                c.set(Calendar.HOUR, 23);
                c.set(Calendar.MINUTE, 59);
                c.set(Calendar.SECOND, 59);
                endDate = c.getTime();
            } catch (ParseException e) {
                logger.error(e.toString(), e);
            }
        }
        if (id != null) {
            cq.setParameter("id", id);
        }
        if (StringUtils.isNotBlank(name)) {
            cq.setParameter("name", "%" + name + "%");
        }
        if (StringUtils.isNotBlank(operateType)) {
            cq.setParameter("operateType", operateType);
        }
        if (StringUtils.isNotBlank(orgName)) {
            cq.setParameter("orgName", Long.valueOf(orgName));
        }
        if (StringUtils.isNotBlank(opName)) {
            cq.setParameter("opName", opName);
        }
        if (StringUtils.isNotBlank(beginTime)) {
            cq.setParameter("beginTime", beginDate);
        }
        if (StringUtils.isNotBlank(endTime)) {
            cq.setParameter("endTime", endDate);
        }
        List<CPContentAndOplog> sql_count = cq.getResultList();
        List<CPContentAndOplog> sql_list = cq
                .setFirstResult(pageable.getPageNumber() * pageable.getPageSize())
                .setMaxResults(pageable.getPageSize()).getResultList();
        em.close();
        Page<CPContentAndOplog> pageImpl = new PageImpl<CPContentAndOplog>(sql_list, pageable,
                sql_count.size());
        return pageImpl;
    }
}
